package com.charging.system;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.charging.common.constant.Constants;

import com.charging.system.domain.KxCard;
import com.charging.system.domain.KxChargingRecord;
import com.charging.system.domain.KxEquip;
import com.charging.system.service.IKxCardService;
import com.charging.system.service.IKxChargingRecordService;
import com.charging.system.service.IKxEquipService;

import org.apache.commons.lang3.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PostMapping;

import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 设备数据上报接收并处理
 */
@RestController
public class ReceiveController {

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Resource
    private IKxEquipService kxEquipService;
    @Resource
    private IKxChargingRecordService kxChargingRecordService;
    @Resource
    private IKxCardService kxCardService;

    /**
     * 设备上线接收数据
     * @param authKey
     * @param chargeno
     * @param channel_num
     * @param gprs
     * @param base_lac
     * @param base_cid
     * @param net_module
     * @param equip_module
     * @param icc_id
     * @param soft_no
     * @param hand_no
     * @param reconnect
     * @return
     */
    @PostMapping("/open/device/online")
    public String deviceOnline(  String authKey, String chargeno, String channel_num,
             String gprs, String base_lac, String base_cid, String net_module,
             String equip_module, String icc_id, String soft_no, String hand_no,
             String reconnect){
        logger.info("设备上线信息：[authKey]"+authKey +"[chargeno]"+chargeno+"[channel_num]"+channel_num
                +"[gprs]"+gprs+"[base_lac]"+base_lac+"[base_cid]"+base_cid+"[net_module]"+net_module
                +"[equip_module]"+equip_module+"[icc_id]"+icc_id+"[soft_no]"+soft_no+"[hand_no]"+hand_no
                +"[reconnect]"+reconnect);
        if(Constants.AUTH_KEY.equals(authKey)){
            KxEquip kxEquip = new KxEquip();
            kxEquip.setEquipNo(chargeno);
            kxEquip.setOnlineStatus(1);
            kxEquip.setSignalIntensity(Integer.getInteger(gprs));
            kxEquip.setBaseCid(base_cid);
            kxEquip.setBaseLac(base_lac);
            kxEquip.setNetModule(net_module);
            kxEquip.setEquipModule(equip_module);
            kxEquip.setRemark(icc_id);
            kxEquip.setSoftNo(soft_no);
            kxEquip.setHandNo(hand_no);
            kxEquipService.updateKxEquipByEquipNo(kxEquip);
            return "ok";
        }else {
            return "error";
        }
    }

    /**
     * 设备离线接收数据
     */
    @PostMapping("/open/device/offline")
    public String deviceOffline(String authKey, String chargeno){
        logger.info("设备离线信息：[authKey]"+authKey +"[chargeno]"+chargeno);
        KxEquip kxEquip = new KxEquip();
        kxEquip.setEquipNo(chargeno);
        kxEquip.setOnlineStatus(0);
        kxEquipService.updateKxEquipByEquipNo(kxEquip);
        return "ok";
    }

    /**
     * 设备上报关闭插座
     * @param authKey
     * @param chargeno
     * @param channelno
     * @param type 打开[1], 关闭[0]
     * @param tpcode 关闭通道原因
     * @param endPower 结束时的功率
     * @param endDegree 结束时的用电量
     * @param eddyTime 浮充时长
     * @return
     */
    @PostMapping("/open/device/close/channel")
    public String deviceCloseChannel(  String authKey, String chargeno, int channelno,
             int type, int tpcode, String endPower, String endDegree, String eddyTime){
        logger.info("设备上报关闭插座：[authKey]"+ authKey +"[chargeno]"+ chargeno+"[channelno]"+ channelno
                +"[type]"+ type+"[tpcode]"+ tpcode+"[endPower]"+ endPower+"[endDegree]"+ endDegree
                +"[eddyTime]"+ eddyTime);
        if(type ==0){
            // 设备主动上报关闭信息
            try{
                int EndType = Constants.EndType.OverByCharging;
                switch (tpcode){
                    case 0 :
                        EndType = Constants.EndType.OverByCharging;
                        break;
                    case 1:
                        EndType = Constants.EndType.NoLoadCurrent;
                        break;
                    case 2:
                        EndType = Constants.EndType.FullStop;
                        break;
                    case 3:
                        EndType = Constants.EndType.Overload;
                        break;
                    case 10:
                        EndType = Constants.EndType.StartButNoCharge;
                        break;
                    case 11:
                        EndType = Constants.EndType.GetMaxChargingTime;
                        break;
                    default:

                }
                kxEquipService.closeChannel(chargeno,channelno,EndType,false);
            }catch (Exception e){
                e.printStackTrace();
                logger.error("上报停止失败："+e.getMessage());
            }
        }
        return "ok";
    }

    /**
     * 设备心跳
     */
    @PostMapping("/open/device/heartbeat")
    public String deviceHeartbeat(String authKey, String chargeno){
        logger.info("设备心跳信息：[chargeno]"+ chargeno);
        return "ok";
    }

    /**
     * 设备告警数据
     */
    @PostMapping("/open/device/alert")
    public String reportDeviceAlert( String authKey, String chargeno, String alertTemp, String alertVoltage,
             String equipAlert, String socketAlert) {
        // 在这里添加业务逻辑来处理设备告警数据
        // 比如验证authKey，记录告警信息到数据库等
        logger.info("设备告警数据：[authKey]"+ authKey +"[chargeno]"+chargeno +"[alertTemp]"+alertTemp +"[alertVoltage]"+alertVoltage
                +"[equipAlert]"+equipAlert +"[socketAlert]"+socketAlert );
        // 假设处理成功，返回ok
        return "ok";
    }
    /**
     * 设备一分钟平均功率
     */
    @PostMapping("/open/device/power/report")
    public String reportDevicePower(String chargeWorkInfo ){
        logger.info("设备一分钟平均功率："+ chargeWorkInfo);
        try {
            JSONObject workInfo = JSONObject.parseObject(chargeWorkInfo);
            String equipNo = workInfo.getString("chargeno");
            int gprs = workInfo.getIntValue("gprs");
            String temp = workInfo.getString("temp");
            String voltage = workInfo.getString("voltage");
            // 更新设备信息
            KxEquip kxEquip = new KxEquip();
            kxEquip.setEquipNo(equipNo);
            kxEquip.setOnlineStatus(1);
            kxEquip.setSignalIntensity(gprs);
            kxEquip.setTemp(temp);
            kxEquip.setVoltage(voltage);
            int updateKxEquip = kxEquipService.updateKxEquipByEquipNo(kxEquip);
            if(updateKxEquip ==1){
//            log.info("设备编号[{}]心跳请求，更新设备状态在线成功",chargeno);
                logger.info("设备编号[{}]充电上报成功，更新设备信号[{}]、设备温度[{}]、设备电压[{}]！",equipNo,gprs,temp,voltage);
            }else {
                logger.info("设备编号[{}]充电上报失败，更新设备信号[{}]、设备温度[{}]、设备电压[{}]！",equipNo,gprs,temp,voltage);
            }
            JSONArray workList = JSONArray.parseArray(workInfo.getString("workList"));
            // 更新设备充电信息
            for (int i =0;i<workList.size();i++){
                JSONObject work = workList.getJSONObject(i);
                int channelno = work.getIntValue("channelno");
                int channelstate = work.getIntValue("channelstate");
                int power = work.getIntValue("power");
                BigDecimal degree = work.getBigDecimal("degree");
                if (channelstate == 1 || channelstate == 2){ // 1：充电中；2：涡流充电；
                    KxChargingRecord kxChargingRecord = new KxChargingRecord();
                    kxChargingRecord.setChargingStatus(Constants.ChargingStatus.INTCHARGING);
                    kxChargingRecord.setChannelNo(channelno);
                    kxChargingRecord.setEquipNo(equipNo);
                    kxChargingRecord.setChargingPower(power);
                    kxChargingRecord.setRemark(degree.toEngineeringString());
                    int updateChargingRecord = kxChargingRecordService.updateChargingPower(kxChargingRecord);
                    if(updateChargingRecord>0){// 更新充电记录
                        logger.info("设备编号[{}]插座号[{}],充电状态[{}], 充电功率[{}] 消耗电度[{}]",equipNo,channelno,channelstate,power,degree);
                    }else {// 如果没有充电记录，确在充电关闭插座
                        kxEquipService.onlyCloseChannel(equipNo,channelno+"");
                    }
                }
            }
            // 反馈当前设备在平台上正在充电的端口
            List<Integer> chargingList = kxChargingRecordService.getEquipChargingNos(equipNo);
            String result = "ok:" + String.join(",", chargingList.stream().map(Object::toString).collect(Collectors.toList()));
            return result;
        }catch (Exception e){
            logger.error("设备一分钟平均功率异常："+e.getMessage());
            return "error";
        }

    }


    /**
     * 查询电卡
     * 该卡无法使用 0
     * 该卡可以使用 1
     * 该卡余额不足 3
     * 该卡正在使用 4
     * 该卡未注册 5
     */
    @PostMapping("/open/query/card")
    public String queryCard(String authKey,String cardno) {
        // 在这里添加业务逻辑来处理设备告警数据
        // 比如验证authKey，记录告警信息到数据库等
        logger.info("查询电卡信息：[authKey]"+ authKey+"[cardno]"+cardno);
        KxCard kxCard = kxCardService.selectKxCardByCardNo(cardno);
        if(ObjectUtils.isNotEmpty(kxCard)){
            if(kxCard.getStatus() == 1){
                KxChargingRecord kxChargingRecord = new KxChargingRecord();
                kxChargingRecord.setCardId(kxCard.getCardId());
                kxChargingRecord.setChargingStatus(Constants.ChargingStatus.INTCHARGING);
                List<KxChargingRecord> kxChargingRecords = kxChargingRecordService.selectKxChargingRecordList(kxChargingRecord);
                if(kxChargingRecords.size()>0){
                    return "error:4";
                }else {
                    BigDecimal total  = kxCard.getBalance().add(kxCard.getGive());
                    if(total.compareTo(BigDecimal.ZERO)==1){// 有余额
                        return "ok:1," + total.setScale(2, RoundingMode.DOWN).multiply(new BigDecimal(100)).toString();
                    }else{// 余额不足
                        return "error:3";
                    }
                }
            }else {
                return "error:0";
            }
        }else {
            return "error:0";
        }
    }

    /**
     * 电卡打开
     */
    @PostMapping("/open/card/openClose")
    public String cardOpenClose( String authKey, String chargeno, int channelno, int type, String cardno) {
        // 在这里添加业务逻辑来处理设备告警数据
        // 比如验证authKey，记录告警信息到数据库等
        logger.info("电卡打开关闭：[authKey]"+ authKey+"[chargeno]"+chargeno+"[channelno]"+channelno+"[type]"+type+"[cardno]"+cardno);
        if(type == 1){// 开启插座
            // 获取当前设备的信息
            KxEquip kxEquip = kxEquipService.getKxEquipByEquipNo(chargeno);
            if (ObjectUtils.isEmpty(kxEquip)) {
                return "error";
            }
            //检查当前插座号是否存在
            int channelNo = channelno;
            if (channelNo < 1 || channelNo > kxEquip.getChannelNum()) {
                return "error";
            }
            // 检查当前插座是否被使用
            KxChargingRecord kxChargingRecordCheck = new KxChargingRecord();
            kxChargingRecordCheck.setChargingStatus(Constants.ChargingStatus.INTCHARGING);
            kxChargingRecordCheck.setEquipNo(chargeno);
            kxChargingRecordCheck.setChannelNo(channelNo);
            List<KxChargingRecord> kxChargingRecordChecks1 = kxChargingRecordService.selectKxChargingRecordList(kxChargingRecordCheck);
            if (kxChargingRecordChecks1.size() > 0) {
                return "error";
            }
            KxCard kxCard = kxCardService.selectKxCardByCardNo(cardno);
            BigDecimal total  = kxCard.getBalance().add(kxCard.getGive());
            if(total.compareTo(BigDecimal.ZERO)==1){// 有余额
                KxChargingRecord kxChargingRecord = new KxChargingRecord();
                kxChargingRecord.setEquipId(kxEquip.getEquipId());
                kxChargingRecord.setEquipNo(kxEquip.getEquipNo());
                kxChargingRecord.setChannelNo(channelNo);
                kxChargingRecord.setCardId(kxCard.getCardId());
                kxChargingRecord.setCardNo(kxCard.getCardNo());
                kxChargingRecord.setEquipType(kxEquip.getEquipType());
                kxChargingRecord.setChargingSchemeId(kxEquip.getChargingSchemeId());
                kxChargingRecord.setAmount(BigDecimal.ZERO);
                kxChargingRecord.setDegree(BigDecimal.ZERO);
                kxChargingRecord.setNumTimes(0);
                kxChargingRecord.setEndType(Constants.EndType.InitChannel);
                kxChargingRecord.setPlanChargingTime(0);
                kxChargingRecord.setChargingPower(0);
                kxChargingRecord.setMaxChargingPower(0);

                kxChargingRecord.setStartPrice(BigDecimal.ZERO);
                kxChargingRecord.setChargingStatus(Constants.ChargingStatus.INTCHARGING);
                int kxChargingRecordInsert = kxChargingRecordService.insertKxChargingRecord(kxChargingRecord);
                if(kxChargingRecordInsert>0){
                    return "ok";
                }else {
                    return "error";
                }
            }else{// 余额不足
                return "error";
            }
        }else {//关闭插座
            try {
                kxEquipService.closeChannel(chargeno,channelno,Constants.EndType.CloseChannel, false);
            }catch (Exception e){
                logger.error("电卡打开关闭设备失败："+e.getMessage());
            }
        }
        // 假设处理成功，返回ok
        return "ok";
    }

}

